package org.jmeter.tcp.helmet;

import com.googlecode.protobuf.format.JsonFormat;
import io.netty.buffer.ByteBuf;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.jmeter.tcp.helmet.client.ConnectionContext;
import org.jmeter.tcp.helmet.client.MessageContext;
import org.jmeter.tcp.helmet.protobuf.util.BuilderUtils;
import org.jmeter.tcp.helmet.protobuf.util.Helmet2ServerMsgBuilder;
import org.jmeter.tcp.helmet.protobuf.HelmetServer;
import org.jmeter.tcp.util.ByteUtils;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author liangsu
 * @version v1.0
 * @Description
 * @Date 2020/11/13 15:23
 * @since
 */
public class HelmetClientSampler extends AbstractSampler {
    private static final Logger log = LoggingManager.getLoggerForClass();
    private final static String IP = "ip";
    private final static String PORT = "port";
    private final static String MSG_TYPE = "msgType";
    private final static String MSG_BODY = "msgBody";
    private final static String DEV_ID = "devId";
    private final static String VERSION = "version";

    public String getMsgType() {
        return getPropertyAsString(MSG_TYPE);
    }

    public void setMsgType(String msgType) {
        setProperty(MSG_TYPE, msgType);
    }

    public String getDevId() {
        return getPropertyAsString(DEV_ID);
    }

    public void setDevId(String devId) {
        setProperty(DEV_ID, devId);
    }

    public String getVersion() {
        return getPropertyAsString(VERSION);
    }

    public void setVersion(String version) {
        setProperty(VERSION, version);
    }

    public Integer getPort() {
        return getPropertyAsInt(PORT);
    }

    public void setPort(Integer port) {
        setProperty(PORT, port);
    }

    public String getIp() {
        return getPropertyAsString(IP);
    }

    public void setIp(String ip) {
        setProperty(IP, ip);
    }

    public void setMsg(String msg){
        setProperty(MSG_BODY, msg);
    }

    public String getMsg(){
        return getPropertyAsString(MSG_BODY);
    }

    @Override
    public SampleResult sample(Entry entry) {
        SampleResult result = new SampleResult();

        result.setSampleLabel(getName());
        result.setSuccessful(false);
        result.setResponseCode("500");

        result.sampleStart(); // 开始
        try {

            // 获取连接
            NioSocketChannel client = ConnectionContext.getNettyClient(getIp(), getPort(), getDevId());

            // 构建消息
            HelmetServer.H2SMessage h2SMessage = Helmet2ServerMsgBuilder
                    .buildHelmet2ServerMsg(getMsgType(), getVersion(), getDevId(), getMsg());

            // 请求消息的json格式
            String strBody = JsonFormat.printToString(h2SMessage);
            int maxLen = 1500;
            if(strBody.length() > maxLen){
                strBody = strBody.substring(0, maxLen) + "...";
            }
            String samplerData = strBody;

            ByteBuf message = BuilderUtils.messageToByteBuf(h2SMessage);

            // 16进制的值
            byte[] bytes = new byte[message.readableBytes()];
            message.getBytes(message.readerIndex(), bytes);
            String hexBody = ByteUtils.bytesToHex(bytes);
            if(hexBody.length() > maxLen){
                hexBody = hexBody.substring(0, maxLen) + "...";
            }
            samplerData += "\n16进制的请求参数: " + hexBody;
            result.setSamplerData(samplerData);

            // 发送消息
            client.writeAndFlush(message);

            try {
                CompletableFuture future = MessageContext.put(client, new CompletableFuture());
                Object responseData = future.get(2, TimeUnit.SECONDS);
                if(responseData != null){
                    result.setResponseData(responseData.toString(), "utf-8");
                    result.setContentType("application/json;charset=UTF-8");
                }
            }catch (TimeoutException e){
                result.setResponseData("获取结果超时", "utf-8");
            }catch (Exception e){
                result.setResponseData("获取结果异常", "utf-8");
            }


            result.setSuccessful(true);
            result.setResponseCode("200");
        }catch (IOException e) {
            log.error("", e);
            result.setResponseData(e.getMessage(), "utf-8");
        }catch (Exception e){
            log.error("未知异常", e);
            result.setResponseData(e.getMessage(), "utf-8");
        }finally {
            result.sampleEnd();
        }
        log.info("开始执行sample方法");

        return result;
    }





}
